#include "MainWindow.hpp"
#include <cairomm/context.h>
#include <cairomm/refptr.h>
#include <gdkmm/pixbuf.h>
#include <gtkmm/drawingarea.h>
#include <mutex>
#include <sigc++/functors/mem_fun.h>

MainWindow::MainWindow() {
  set_title("大屏幕");
  maximize();
  m_Notebook.append_page(drawArea, "Alphapose");
  m_Notebook.append_page(drawCamera1, "Camera1");
  m_Notebook.append_page(drawCamera2, "Camera2");
  m_Notebook.append_page(drawCamera3, "Camera3");
  m_Notebook.append_page(drawCamera4, "Camera4");
  m_Notebook.append_page(drawCamera5, "Camera5");
  set_child(m_Notebook);
  SetNewImage(1440, 1080, new unsigned char[1440 * 1080 * 3], 0);
  SetNewImage(1440, 1080, new unsigned char[1440 * 1080 * 3], 1);
  SetNewImage(1440, 1080, new unsigned char[1440 * 1080 * 3], 2);
  SetNewImage(1440, 1080, new unsigned char[1440 * 1080 * 3], 3);
  SetNewImage(1440, 1080, new unsigned char[1440 * 1080 * 3], 4);
  SetNewImage(1440, 1080, new unsigned char[1440 * 1080 * 3], 5);
  drawArea.set_draw_func(
      sigc::bind(sigc::mem_fun(*this, &MainWindow::DrawAction), 0));
  drawCamera1.set_draw_func(
      sigc::bind(sigc::mem_fun(*this, &MainWindow::DrawAction), 1));
  drawCamera2.set_draw_func(
      sigc::bind(sigc::mem_fun(*this, &MainWindow::DrawAction), 2));
  drawCamera3.set_draw_func(
      sigc::bind(sigc::mem_fun(*this, &MainWindow::DrawAction), 3));
  drawCamera4.set_draw_func(
      sigc::bind(sigc::mem_fun(*this, &MainWindow::DrawAction), 4));
  drawCamera5.set_draw_func(
      sigc::bind(sigc::mem_fun(*this, &MainWindow::DrawAction), 5));
  signal_close_request().connect(sigc::mem_fun(*this, &MainWindow::onclose),
                                 true);
  m_Dispatcher.connect(sigc::mem_fun(*this, &MainWindow::refresh_call));
}

bool MainWindow::onclose() {
  destroy();
  return true;
}

void MainWindow::refresh_call() { drawArea.queue_draw(); }

void MainWindow::refreshUI() { m_Dispatcher.emit(); }

void MainWindow::DrawAction(const Cairo::RefPtr<Cairo::Context> &context,
                            int width, int height, int index) {
  std::lock_guard<std::mutex> lock(mut);
  switch (index) {
  case 0:
    Gdk::Cairo::set_source_pixbuf(context, imageBuf, 0, 0);
    context->rectangle(0, 0, imageBuf->get_width(), imageBuf->get_height());
    break;
  case 1:
    Gdk::Cairo::set_source_pixbuf(context, image1, 0, 0);
    context->rectangle(0, 0, image1->get_width(), image1->get_height());
    break;
  case 2:
    Gdk::Cairo::set_source_pixbuf(context, image2, 0, 0);
    context->rectangle(0, 0, image2->get_width(), image2->get_height());
    break;
  case 3:
    Gdk::Cairo::set_source_pixbuf(context, image3, 0, 0);
    context->rectangle(0, 0, image3->get_width(), image3->get_height());
    break;
  case 4:
    Gdk::Cairo::set_source_pixbuf(context, image4, 0, 0);
    context->rectangle(0, 0, image4->get_width(), image4->get_height());
    break;
  case 5:
    Gdk::Cairo::set_source_pixbuf(context, image5, 0, 0);
    context->rectangle(0, 0, image5->get_width(), image5->get_height());
    break;
  }
  context->fill();
}

void MainWindow::SetNewImage(int width, int height, unsigned char *data,
                             int index) {
  std::lock_guard<std::mutex> lock(mut);
  switch (index) {
  case 0:
    imageBuf = Gdk::Pixbuf::create_from_data(
        (const guint8 *)data, Gdk::Colorspace::RGB, false, 8, width, height,
        width * 3, [](const guint8 *data) { delete[] data; });
    break;
  case 1:
    image1 = Gdk::Pixbuf::create_from_data(
        (const guint8 *)data, Gdk::Colorspace::RGB, false, 8, width, height,
        width * 3, [](const guint8 *data) { delete[] data; });
    break;
  case 2:
    image2 = Gdk::Pixbuf::create_from_data(
        (const guint8 *)data, Gdk::Colorspace::RGB, false, 8, width, height,
        width * 3, [](const guint8 *data) { delete[] data; });
    break;
  case 3:
    image3 = Gdk::Pixbuf::create_from_data(
        (const guint8 *)data, Gdk::Colorspace::RGB, false, 8, width, height,
        width * 3, [](const guint8 *data) { delete[] data; });
    break;
  case 4:
    image4 = Gdk::Pixbuf::create_from_data(
        (const guint8 *)data, Gdk::Colorspace::RGB, false, 8, width, height,
        width * 3, [](const guint8 *data) { delete[] data; });
    break;
  case 5:
    image5 = Gdk::Pixbuf::create_from_data(
        (const guint8 *)data, Gdk::Colorspace::RGB, false, 8, width, height,
        width * 3, [](const guint8 *data) { delete[] data; });
    break;
  }
}
